<?php

namespace api\modules\v1\forms\task;

use Yii;
use yii\base\Model;
use common\models\task\Task;
use services\common\CommonService;
use services\task\TaskService;

/**
 * 动作
 *
 * Class TaskForm
 * @package api\modules\v1\forms\task
 */
class TaskForm extends Model
{
    // 任务ID
    public $id;
    // 标题
    public $title;
    // 任务开始时间
    public $start_time;
    // 任务结束时间
    public $end_time;
    // 备注
    public $remark;
    // 关闭原因
    public $reason;
    // 任务人
    public $member_ids;
    // 患者IDs
    public $patient_ids;
    // 挂号【开始时间】
    public $start_reg_time;
    // 挂号【结束时间】
    public $end_reg_time;
    // 最后回访【开始时间】
    public $start_last_callback_time;
    // 最后回访【结束时间】
    public $end_last_callback_time;
    // 未到天数【最小值】
    public $start_missed_days;
    // 未到天数【最大值】
    public $end_missed_days;
    // 308剩余量【最小值】
    public $start_surplus_num;
    // 308剩余量【最大值】
    public $end_surplus_num;
    // 就诊类型IDs
    public $outpatient_type_ids;
    // 标签IDs
    public $tag_ids;
    // 一级病种IDs
    public $patient_diseases_ids;
    // 是否为抗复发
    public $is_anti_relapse;
    // 钉钉机器人access_token
    public $access_token;
    // 钉钉机器人secret
    public $secret;
    // 提醒内容【json {状态: 内容}】
    public $content;


    // 任务信息
    protected $_taskInfo;
    // 权限下归属人列表
    protected $_limitMemberList;
    // 提醒内容数组
    protected $_contentArr;


    public function rules()
    {
        return [
            // 参数验证
            [['title', 'start_time', 'end_time', 'member_ids', 'patient_ids'], 'required', 'message' => '{attribute}不能为空', 'on' => ['create']],
            [['id', 'title', 'start_time', 'end_time', 'member_ids', 'patient_ids'], 'required', 'message' => '{attribute}不能为空', 'on' => ['edit']],
            [['id'], 'required', 'message' => '{attribute}不能为空', 'on' => ['delete']],
            [['id', 'reason'], 'required', 'message' => '{attribute}不能为空', 'on' => ['close']],
            [['id', 'access_token', 'content'], 'required', 'message' => '{attribute}不能为空', 'on' => ['remind']],

            [['id'], 'checkId', 'skipOnEmpty' => false, 'on' => ['edit', 'delete', 'close', 'remind']],
            [['title'], 'checkTitle', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['start_time'], 'checkStartTime', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['end_time'], 'checkEndTime', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['member_ids'], 'checkMemberIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['patient_ids'], 'checkPatientIds', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['start_reg_time'], 'checkRegTime', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['start_last_callback_time'], 'checkLastCallbackTime', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['start_missed_days'], 'checkMissedDays', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['start_surplus_num'], 'checkSurplusNum', 'skipOnEmpty' => false, 'on' => ['create', 'edit']],
            [['reason'], 'checkReason', 'skipOnEmpty' => false, 'on' => ['close']],
            [['content'], 'checkContent', 'skipOnEmpty' => false, 'on' => ['remind']],
        ];
    }

    public function scenarios()
    {
        $scenarios = parent::scenarios();

        // 新增
        $scenarios['create'] = [
            'title', 'remark', 'start_time', 'end_time', 'member_ids', 'patient_ids',

            'start_reg_time', 'end_reg_time', 'start_last_callback_time', 'end_last_callback_time',
            'start_missed_days', 'end_missed_days', 'start_surplus_num', 'end_surplus_num',
            'outpatient_type_ids', 'tag_ids', 'patient_diseases_ids', 'is_anti_relapse',
        ];

        // 编辑【未开始】
        $scenarios['edit'] = [
            'id', 'title', 'remark', 'start_time', 'end_time', 'member_ids', 'patient_ids',

            'start_reg_time', 'end_reg_time', 'start_last_callback_time', 'end_last_callback_time',
            'start_missed_days', 'end_missed_days', 'start_surplus_num', 'end_surplus_num',
            'outpatient_type_ids', 'tag_ids', 'patient_diseases_ids', 'is_anti_relapse',
        ];

        // 删除
        $scenarios['delete'] = ['id'];

        // 关闭【进行中、已延期】
        $scenarios['close'] = ['id', 'reason'];

        // 提醒
        $scenarios['remind'] = ['id', 'access_token', 'secret', 'content'];

        return $scenarios;
    }

    /**
     * @return array
     */
    public function attributeLabels()
    {
        return [
            'id' => '任务ID',
            'title' => '标题',
            'remark' => '备注',
            'start_time' => '任务开始时间',
            'end_time' => '任务结束时间',
            'member_ids' => '任务人',
            'patient_ids' => '患者',
            'reason' => '关闭原因',
            'access_token' => '钉钉token',
            'secret' => '钉钉secret',
        ];
    }

    /**
     * 检验任务信息
     *
     * @param $attribute
     * @return bool
     */
    public function checkId($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $task = $this->getTaskInfo();
        if (empty($task)) {
            $this->addError($attribute, '任务不存在');
            return true;
        }
        if ($task->project_id != Yii::$app->params['project_id']) {
            $this->addError($attribute, '任务非当前项目');
            return true;
        }

        $limitMemberList = $this->getLimitMemberList();
        $limitMemberIds = array_column($limitMemberList, 'id');
        $limitMemberIds[] = Yii::$app->user->identity->member_id;
        if (!in_array($task->created_member_id, $limitMemberIds)) {
            $this->addError($attribute, '无权限操作该任务');
            return true;
        }

        // 状态修复为定义状态
        $service = new TaskService();
        $status = $service->getTrueStatus((int)$task->status, $task->start_time, $task->end_time);

        if ($this->getScenario() == 'edit') {
            if ($status != Task::STATUS_WAIT) {
                $this->addError($attribute, '任务非等待状态，无法编辑');
                return true;
            }
        } elseif ($this->getScenario() == 'close') {
            if (!in_array($status, [Task::STATUS_START, Task::STATUS_DELAY])) {
                $this->addError($attribute, '任务状态非进行中');
                return true;
            }
        }

        if ($status == Task::STATUS_DELETE) {
            $this->addError($attribute, '任务已删除');
            return true;
        }
    }

    /**
     * 校验任务名称
     *
     * @param $attribute
     */
    public function checkTitle($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $len = mb_strlen($this->title);
        if ($len > 10) {
            $this->addError($attribute, '任务名称过长，最多10个字');
            return true;
        }
    }

    /**
     * 校验任务开始时间
     *
     * @param $attribute
     */
    public function checkStartTime($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $nowTime = strtotime(date('Y-m-d'));
        if (strtotime($this->start_time) < $nowTime) {
            $this->addError($attribute, '任务开始时间不能小于当天');
            return true;
        }
    }

    /**
     * 校验任务结束时间
     *
     * @param $attribute
     */
    public function checkEndTime($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (strtotime($this->start_time) > strtotime($this->end_time)) {
            $this->addError($attribute, '任务结束时间不能小于开始时间');
            return true;
        }
    }

    /**
     * 校验挂号时间
     *
     * @param $attribute
     */
    public function checkRegTime($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if ($this->start_reg_time && $this->end_reg_time && strtotime($this->start_reg_time) > strtotime($this->end_reg_time)) {
            $this->addError($attribute, '挂号结束时间不能小于开始时间');
            return true;
        }
    }

    /**
     * 校验上次回访时间
     *
     * @param $attribute
     */
    public function checkLastCallbackTime($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if ($this->start_last_callback_time
            && $this->end_last_callback_time
            && strtotime($this->start_last_callback_time) > strtotime($this->end_last_callback_time)) {
            $this->addError($attribute, '上次回访结束时间不能小于开始时间');
            return true;
        }
    }

    /**
     * 校验未到天数
     *
     * @param $attribute
     */
    public function checkMissedDays($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (!is_numeric($this->start_missed_days) && !is_numeric($this->end_missed_days)) {
            return true;
        }

        if (!is_numeric($this->start_missed_days)) {
            $this->addError($attribute, '未到最小天数不能为空');
            return true;
        }

        if (!is_numeric($this->end_missed_days)) {
            $this->addError($attribute, '未到最大天数不能为空');
            return true;
        }

        if ($this->start_missed_days < 0) {
            $this->addError($attribute, '未到最小天数不能小于0');
            return true;
        }

        if ($this->end_missed_days > 9999) {
            $this->addError($attribute, '未到最大天数不能大于9999');
            return true;
        }

        if ($this->start_missed_days > $this->end_missed_days) {
            $this->addError($attribute, '未到最大天数不能小于最小天数');
            return true;
        }
    }

    /**
     * 校验308剩余数
     *
     * @param $attribute
     */
    public function checkSurplusNum($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        if (!is_numeric($this->start_surplus_num) && !is_numeric($this->end_surplus_num)) {
            return true;
        }

        if (!is_numeric($this->start_surplus_num)) {
            $this->addError($attribute, '308剩余最小数不能为空');
            return true;
        }

        if (!is_numeric($this->end_surplus_num)) {
            $this->addError($attribute, '308剩余最大数不能为空');
            return true;
        }

        if ($this->start_surplus_num < -999) {
            $this->addError($attribute, '308剩余最小数不能小于-999');
            return true;
        }

        if ($this->end_surplus_num > 9999) {
            $this->addError($attribute, '308剩余最大数不能大于9999');
            return true;
        }

        if ($this->start_surplus_num > $this->end_surplus_num) {
            $this->addError($attribute, '308剩余最大数不能小于最小数');
            return true;
        }
    }

    /**
     * 校验任务人
     *
     * @param $attribute
     */
    public function checkMemberIds($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $memberIds = $this->getMemberIds();

        $limitMemberList = $this->getLimitMemberList();
        $limitMemberIds = array_column($limitMemberList, 'id');
        foreach ($memberIds as $row) {
            if (!in_array($row, $limitMemberIds)) {
                $this->addError($attribute, '任务人错误，存在非权限下人员');
                return true;
            }
        }
    }

    /**
     * 校验患者
     *
     * @param $attribute
     */
    public function checkPatientIds($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $patientIds = $this->getPatientIds();
        if (count($patientIds) == 0) {
            $this->addError($attribute, '任务患者不能为空');
            return true;
        }
    }

    /**
     * 校验关闭原因
     *
     * @param $attribute
     */
    public function checkReason($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $len = mb_strlen($this->reason);
        if ($len > 256) {
            $this->addError($attribute, '关闭原因过长，最多256个字');
            return true;
        }
    }

    /**
     * 校验提醒内容
     *
     * @param $attribute
     */
    public function checkContent($attribute)
    {
        if ($this->hasErrors()) {
            return true;
        }

        $status = [Task::STATUS_START, Task::STATUS_DELAY, Task::STATUS_SUCCESS, Task::STATUS_CLOSE];

        $contentArr = $this->getRemindContent();
        $data = [];
        foreach ($status as $row) {
            if (isset($contentArr[$row])) {
                if (empty($contentArr[$row])) {
                    $this->addError($attribute, '提醒内容不能为空');
                    return true;
                }

                $len = mb_strlen($contentArr[$row]);
                if ($len > 200) {
                    $this->addError($attribute, '提醒内容过长，最多200字');
                    return true;
                }

                $data[$row] = trim($contentArr[$row]);
            }
        }

        if (empty($data)) {
            $this->addError($attribute, '提醒内容不能为空');
            return true;
        }

        $this->_contentArr = $data;
    }

    /**
     * 获取任务信息
     *
     * @return Task|null
     */
    public function getTaskInfo(): ?Task
    {
        if (empty($this->_taskInfo)) {
            $this->_taskInfo = Task::findOne($this->id);
        }

        return $this->_taskInfo;
    }

    /**
     * 获取归属人列表
     *
     * @return array
     */
    public function getLimitMemberList(): array
    {
        if (empty($this->_limitMemberList)) {
            $this->_limitMemberList = CommonService::getMemberList(3);
        }

        return $this->_limitMemberList;
    }

    /**
     * 获取任务人IDs
     *
     * @return array
     */
    public function getMemberIds(): array
    {
        $ids = is_array($this->member_ids) ? $this->member_ids : explode(',', $this->member_ids);
        return array_unique($ids);
    }

    /**
     * 获取患者IDs
     *
     * @return array
     */
    public function getPatientIds(): array
    {
        $ids = is_array($this->patient_ids) ? $this->patient_ids : explode(',', $this->patient_ids);
        return array_unique($ids);
    }

    /**
     * 获取就诊类型IDs
     *
     * @return array
     */
    public function getOutpatientTypeIds(): array
    {
        $ids = is_array($this->outpatient_type_ids)
            ? $this->outpatient_type_ids
            : $this->outpatient_type_ids ? explode(',', $this->outpatient_type_ids) : [];
        return array_unique($ids);
    }

    /**
     * 获取标签IDs
     *
     * @return array
     */
    public function getTagIds(): array
    {
        $ids = is_array($this->tag_ids)
            ? $this->tag_ids
            : $this->tag_ids ? explode(',', $this->tag_ids) : [];
        return array_unique($ids);
    }

    /**
     * 获取病种IDs
     *
     * @return array
     */
    public function getPatientDiseasesIds(): array
    {
        $ids = is_array($this->patient_diseases_ids)
            ? $this->patient_diseases_ids
            : $this->patient_diseases_ids ? explode(',', $this->patient_diseases_ids) : [];
        return array_unique($ids);
    }

    /**
     * 获取提醒内容
     *
     * @return array
     */
    public function getRemindContent(): array
    {
        if (empty($this->_contentArr)) {
            $this->_contentArr = json_decode($this->content, true);
        }

        return $this->_contentArr;
    }
}
